/*
*/

#include <keypad.h>
#include <beam.h>
#include <display.h>
#include <event.h>
#include <form.h>
#include <keypad.h>
#include <rtc.h>
#include <test.h>
#include <timer.h>
#include <sensor.h>
#include <usb.h>

#define	KEY_MASK	0x07e0

typedef u32(*KEYPR)(u32);

static u32	KeyBak	(u32);
static u32	KeyChM	(u32);
static u32	KeyChP	(u32);
static u32	KeyNum	(u32);
static u32	KeyPag	(u32);
static u32	KeyPro	(u32);
static u32	KeyReg	(u32);
static u32	KeyRep	(u32);
static u32	KeySar	(u32);
static u32	KeyTst	(u32);

static u32	ch_key=0;
static u32	ch_int=1;
static u32	ch_max=300;
static u32	ch_min=1;

static u32 KeyBak(u32 key){
    return MOD_NIL;
}

static u32 KeyChM(u32 key){
    ch_int--;
    if(ch_int<ch_min)
	ch_int=ch_max;
    if(ch_int>ch_max)
	ch_int=ch_max;
    return MOD_NIL;
}

static u32 KeyChP(u32 key){
    ch_int++;
    if(ch_int<ch_min)
	ch_int=ch_min;
    if(ch_int>ch_max)
	ch_int=ch_min;
    return MOD_NIL;
}

static u32 KeyNum(u32 key){
    if(key>9)
	key=0;
    ch_key=ch_key*10+key;
    if(ch_key>999)
	ch_key%=1000;
    ch_int=ch_key;
    return MOD_NIL;
}

static u32 KeyPag(u32 key){
    Page(key-KEY___TV);
    IndicatorOn();
    return MOD_SEARCH;
}

static u32 KeyPro(u32 key){
    return MOD_LEARNING;
}

static u32 KeyReg(u32 key){
    return MOD_NIL;
}

static u32 KeyRep(u32 key){
    return MOD_NIL;
}

static u32 KeySar(u32 key){
    return MOD_NIL;
}

static u32 KeyTst(u32 key){
    test=TestRTC;
    return MOD_TEST;
}

//------------------------------------------------------------------------------

void InitKeypad(void){
}

u32 KeyEvent(void){
    static u32	o,t=CLK_NIL;
    const u8 keymap[8][6]={
	{KEY_RESV,KEY_RESV,KEY___TV,KEY____1,KEY____2,KEY____3},
	{KEY_CABL,KEY____4,KEY____5,KEY____6,KEY__DVD,KEY____7},
	{KEY____8,KEY____9,KEY__AUX,KEY_DIGI,KEY____0,KEY_DISP},
	{KEY_MENU,KEY_UPPP,KEY_EXIT,KEY_LEFT,KEY_OKEY,KEY_RGHT},
	{KEY_INFO,KEY_DOWN,KEY_ENTR,KEY_STTL,KEY_ANGL,KEY_ZOOM},
	{KEY_LANG,KEY_PWER,KEY_RECR,KEY_STOP,KEY_EJCT,KEY_BKWD},
	{KEY_PLAY,KEY_FRWD,KEY_VOLI,KEY_RESV,KEY_CHLI,KEY_BACK},
	{KEY_MUTE,KEY_CHLD,KEY_VOLD,KEY_RESV,KEY_PROG,KEY_STAR}
    };
    u8	c,r;
    u16 k,s;

    GPIO_Write(GPIOB,0xf000);	//Turn off all LEDs
    k=GPIO_ReadInputData(GPIOA)&KEY_MASK;
    if(k!=KEY_MASK){
	if(!o){
	    if(t==CLK_NIL)
		t=(clock+16)&CLK_MASK;
	    else if(clock>t){
		s=4;
		for(r=0;r<8;r++){
		    GPIO_Write(GPIOB,(~s)&0xfffc);
		    k=GPIO_ReadInputData(GPIOA)&KEY_MASK;
		    if(k!=KEY_MASK){
			k>>=5;
			for(c=0;c<6;c++){
			    if(!(k&1)){
				o=keymap[r][c];
				t=CLK_NIL;
				return (o<<16)+EVN_KEYPRESS;
			    }
			    k>>=1;
			}
		    }
		    s<<=1;
		}
		o=255;
		t=CLK_NIL;
	    }
	}
    }
    else if(o){
	if(t==CLK_NIL)
	    t=(clock+16)&CLK_MASK;
	else if(clock>t){
	    t=CLK_NIL;
	    o=0;
	    return EVN_KEYRELEASE;
	}
    }
    return 0;
}

u32 KeyPress(u32 key){
    const KEYPR prs[]={
	KeyReg,KeyNum,KeyNum,KeyNum,KeyNum,KeyNum,KeyNum,KeyNum,
	KeyNum,KeyNum,KeyNum,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,
	KeyChP,KeyChM,KeyRep,KeyRep,KeyReg,KeyReg,KeyReg,KeyReg,
	KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,
	KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeyTst,
	KeyTst,KeyTst,KeyTst,KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,
	KeyReg,KeyReg,KeyPag,KeyPag,KeyPag,KeyPag,KeyPag,KeyPag,
	KeyReg,KeyReg,KeyReg,KeyReg,KeyReg,KeySar,KeyBak,KeyPro
    };
    u32	evn,rep,ret,stt,t_b,t_c,t_s;

    info.key=key;
    SendInfo();
    ret=MOD_NIL;
    t_s=beam.timeout;
    t_b=Timer();
    stt=prs[key](key);
    t_c=stt?t_b:0;
    //BeamOn(key);
    do{
	evn=WaitEvent()&EVN_MASK;
	if(stt&&TimeOut(t_c,3000)){
	    evn=EVN_KEYRELEASE;
	    ret=stt;
	}
	else if((rep=beam.timeout)&&TimeOut(t_b,rep)){
	    t_b=Timer();
	    //BeamCont();
	}
    }while(evn!=EVN_KEYRELEASE);
    BeamOff();
    beam.timeout=t_s;
    info.key=0;
    SendInfo();
    return ret;
}
